//
//  WYWDownLoader.m
//  WYWDownloader
//
//  Created by Mr.Run on 2017/11/6.
//  Copyright © 2017年 Mr.Run. All rights reserved.
//

#import "WYWDownLoader.h"
#import "WYWFileTool.h"

#define kCachePath NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject
#define kTmpPath NSTemporaryDirectory()

@interface WYWDownLoader ()<NSURLSessionDataDelegate>
{
    long long _tmpSize;
    long long _totalSize;
}
@property (nonatomic,strong) NSURLSession *session;
@property (nonatomic,copy) NSString *downLoadedPath;
@property (nonatomic,copy) NSString *downLoadingPath;
@property (nonatomic,strong) NSOutputStream *outputStream;
@property (nonatomic,weak) NSURLSessionDataTask *dataTask;
@end

@implementation WYWDownLoader

- (NSURLSession *)session{
    if (!_session) {
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}

-(void)downLoader:(NSURL *)url downLoadInfo:(DownLoadInfoType)downLoadInfo progress:(ProgressBlockType)progress success:(SuccessBlockType)success failed:(FailedBlockType)failed{
    
    self.downLoadInfo = downLoadInfo;
    self.progressChange = progress;
    self.successBlock = success;
    self.failedBlock = failed;
    
    [self downLoader:url];
}

-(void)downLoader:(NSURL *)url{
    
    if ([url isEqual:self.dataTask.originalRequest.URL]) {
        if (self.state == WYWDownLoadStatePause) {
            [self resumeCurrentTask];
            return;
        }
    }
    [self cancelCurrentTask];
    NSString *fileName = url.lastPathComponent;
    self.downLoadedPath = [kCachePath stringByAppendingPathComponent:fileName];
    self.downLoadingPath = [kTmpPath stringByAppendingPathComponent:fileName];
    
    if ([WYWFileTool fileExists:self.downLoadedPath]) {
        
        //UNDO: 已经存在, 告诉外界
//        NSLog(@"%s~~~%d~~~已经下载完成",__func__,__LINE__);
        self.state = WYWDownLoadStatePauseSuccess;
        return;
    }
    
//    if (![WYWFileTool fileExists:downLoadingPath]) {
//        [self downLoadWithURL:url offset:0];
//        return;
//    }
    
    _tmpSize = [WYWFileTool fileSize:self.downLoadingPath];
    
    [self downLoadWithURL:url offset:_tmpSize];
    
//    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//    request.HTTPMethod = @"HEAD";
//    NSHTTPURLResponse *response = nil;
//    NSError *error = nil;
//    [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//    
//    if (error == nil) {
//        NSLog(@"%s~~~%d~~~%@",__func__,__LINE__,response.allHeaderFields[@"Content-Length"]);
//    }
    
}

-(void)pauseCurrentTask{
    
    if (self.state == WYWDownLoadStateDownLoading) {
        self.state = WYWDownLoadStatePause;
        [self.dataTask suspend];
    }
}
    
-(void)cancelCurrentTask{
    self.state = WYWDownLoadStatePause;
    [self.session invalidateAndCancel];
    self.session = nil;
    
}
 
-(void)resumeCurrentTask{
    
    if (self.dataTask && self.state == WYWDownLoadStatePause) {
        [self.dataTask resume];
        self.state = WYWDownLoadStateDownLoading;
    }
}

-(void)cancelAndClean{
    [self cancelCurrentTask];
    [WYWFileTool removeFile:self.downLoadingPath];
}

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
//    NSLog(@"%s~~~%d~~~%@",__func__,__LINE__,response);
//    NSLog(@"%s~~~%d~~~%@",__func__,__LINE__,[NSThread currentThread]);
    _totalSize = [response.allHeaderFields[@"Content-Length"] longLongValue];
    NSString *contentRangeStr = response.allHeaderFields[@"Content-Range"];
    
    if (contentRangeStr.length != 0) {
        _totalSize = [[contentRangeStr componentsSeparatedByString:@"/"].lastObject longLongValue];
    }
    
    if (self.downLoadInfo != nil) {
        self.downLoadInfo(_totalSize);
    }
    
    if (_tmpSize == _totalSize) {
//        NSLog(@"%s~~~%d~~~移动下载的文件到完成文件",__func__,__LINE__);
        [WYWFileTool moveFile:self.downLoadingPath toPath:self.downLoadedPath];
        completionHandler(NSURLSessionResponseCancel);
        self.state = WYWDownLoadStatePauseSuccess;
        return;
    }
    
    if (_tmpSize > _totalSize) {
//        NSLog(@"%s~~~%d~~~删除临时缓存, 重新开始下载",__func__,__LINE__);
        [WYWFileTool removeFile:self.downLoadingPath];
        [self downLoader:response.URL];
        completionHandler(NSURLSessionResponseCancel);
        return;
    }
    self.state = WYWDownLoadStateDownLoading;
    self.outputStream = [NSOutputStream outputStreamToFileAtPath:self.downLoadingPath append:YES];
    [self.outputStream open];
    completionHandler(NSURLSessionResponseAllow);
}

-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    _tmpSize += data.length;
    self.progress = 1.0*_tmpSize/_totalSize;
    [self.outputStream write:data.bytes maxLength:data.length];
//    NSLog(@"%s~~~%d~~~接收后续数据",__func__,__LINE__);
}

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
//    NSLog(@"%s~~~%d~~~完成",__func__,__LINE__);
    if (error == nil) {
        //UNDO: 此处有 MD5 验证文件是否完整, 一下默认完整
        [WYWFileTool moveFile:self.downLoadingPath toPath:self.downLoadedPath];
        self.state = WYWDownLoadStatePauseSuccess;
    }else{
        // 取消, 或者断网
        if (error.code == -999) {
            self.state = WYWDownLoadStatePause;
        }else{
            NSLog(@"%zd~~~%@~~~有问题",error.code,error.localizedDescription);
            self.state = WYWDownLoadStatePauseFailed;
        }
    }
    [self.outputStream close];
}

-(void)downLoadWithURL:(NSURL *)url offset:(long long)offset{
//    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
//    NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:0];
    [request setValue:[NSString stringWithFormat:@"bytes=%lld-", offset] forHTTPHeaderField:@"Range"];
    self.dataTask = [self.session dataTaskWithRequest:request];
//    [self.dataTask resume];
    [self resumeCurrentTask];
}

-(void)setState:(WYWDownLoadState)state{
    if (_state == state) {
        return;
    }
    _state = state;
    
    if (self.stateChange) {
        self.stateChange(_state);
    }
    
    if (_state == WYWDownLoadStatePauseSuccess && self.successBlock) {
        self.successBlock(self.downLoadedPath);
    }
    
    if (_state == WYWDownLoadStatePauseFailed && self.failedBlock) {
        #warning TODO: 错误信息
        self.failedBlock();
    }
    
}

-(void)setProgress:(CGFloat)progress{
    _progress = progress;
    if (self.progressChange) {
        self.progressChange(_progress);
    }
}

@end
